#ifndef HTTP_HTTP_SESSION_H_
#define HTTP_HTTP_SESSION_H_
#include <fermat/common/any.h>
#include <fermat/net/iobuffer.h>
#include <fermat/common/timestamp.h>
#include <fermat/http/http_request.h>
#include <fermat/http/http_response_builder.h>
#include <fermat/net/tcp_connection.h>
#include <string>
#include <list>
#include <memory>
using fermat::any;
using fermat::Timestamp;
//using fermat::net::Buffer;
using fermat::net::TcpConnectionPtr;
using fermat::net::TcpConnection;

namespace fermat {
namespace http {

class HttpServerSession;
typedef std::function<bool(RequestPtr, HttpServerSession*)>           RequestReady;
typedef std::function<bool(ResponseBuilderPtr&, HttpServerSession*)>  ResponseWriteComplete;
typedef std::function<bool(ResponseBuilderPtr&, std::string&)>        ResponseWrite;
typedef std::function<bool(HttpServerSession*)>                       SessionCB;
typedef std::function<RequestPtr()>                                   RequestFactory;                         
class HttpServerSession {
public:
	HttpServerSession(const TcpConnectionPtr &con);
	virtual ~HttpServerSession();

	void setContext(any & c);

	void setRequestCreate(const RequestFactory &factor);
	
	bool parseMessage(PageBufferSliceQueuePtr buf, Timestamp &recvtime);

	bool gotCurrentMessage();

	void postResponse(const ResponseBuilderPtr & res);

	void sendMessage();

	void onSendComplete();

	bool closeConnection();

	

	void setClose(bool ifclose);
	//must set
	void setRequestReadyCB(const RequestReady &cb);
	//must set
	void setResponseWriteComplete(const ResponseWriteComplete &cb);
	void setResponseWrite(const ResponseWrite &cb);
	// not must set
	void setOnParseError(const SessionCB &cb);
private:
	void sendMessageInloop();
	bool isSendComplete();
	void processBadRequest();
private:
	RequestReady                   _reqReady;
	ResponseWriteComplete          _resWriteComplete;
	SessionCB                      _onParseError;
	RequestFactory                 _factory;
	ResponseWrite                  _resWrite;
	
private:
	std::weak_ptr<TcpConnection>    _conn;
	bool                            _close;
	Timestamp                       _lastRecv;
	any                             _context;
	RequestPtr                      _currentRequest;
	ResponseBuilderPtr              _currentResponse;
};

typedef std::shared_ptr<HttpServerSession> HttpServerSessionPtr;
}
}
#endif